#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <unistd.h>     // POSIX操作系统API
#include <pthread.h>     // POSIX线程库
#include "LockGuard.hpp" // 自定义的RAII风格锁

using namespace std;

// 全局互斥锁，静态初始化
pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;

#define NUM 4  // 定义线程数量

// 线程数据类，用于存储每个线程的信息
class threadData
{
public:
    // 构造函数，注意注释掉的mutex参数
    // 早期版本可能将锁作为参数传入，现在改用全局锁
    threadData(int number /*, pthread_mutex_t *mutex*/)
    {
        threadname = "thread-" + to_string(number);
        // lock = mutex;  // 早期版本代码，现在使用全局锁
    }

public:
    string threadname;  // 线程名称
    // pthread_mutex_t *lock;  // 早期版本：指向互斥锁的指针
};

// 模拟3000张票
int tickets = 3000; // 共享资源，用多线程模拟抢票场景

// 线程执行函数
void *getTicket(void *args)
{
    threadData *td = static_cast<threadData *>(args);
    const char *name = td->threadname.c_str();
    while (true)
    {
        // 当前版本：展示错误的双重加锁，会导致死锁
        pthread_mutex_lock(&lock); // 第一次加锁
        pthread_mutex_lock(&lock); // 第二次加锁 - 死锁！线程会在这里永远等待

        if(tickets > 0)
        {
            usleep(1000);  // 模拟获取票的耗时操作
            printf("who=%s, get a ticket: %d\n", name, tickets);
            tickets--;
            // pthread_mutex_unlock(td->lock);  // 早期版本解锁代码
            // pthread_mutex_unlock(&lock);     // 早期版本解锁代码
        }
        else{
            // pthread_mutex_unlock(td->lock);  // 早期版本解锁代码
            // pthread_mutex_unlock(&lock);     // 早期版本解锁代码
            break;
        }
        usleep(13); // 模拟抢票后的其他操作耗时
    }
    printf("%s ... quit\n", name);
    return nullptr;
}

// 下面是使用RAII风格的LockGuard的更安全版本
/*
void *getTicket(void *args)
{
    threadData *td = static_cast<threadData *>(args);
    const char *name = td->threadname.c_str();
    while (true)
    {
        {   // 作用域块，确保LockGuard的生命周期
            LockGuard lockguard(&lock); // RAII风格加锁，离开作用域自动解锁
            if (tickets > 0)
            {
                usleep(1000);
                printf("who=%s, get a ticket: %d\n", name, tickets);
                tickets--;
            }
            else
                break;
        }
        usleep(13);
    }
    printf("%s ... quit\n", name);
    return nullptr;
}
*/

int main()
{
    // pthread_mutex_init(&lock, nullptr);  // 如果不使用静态初始化，这里需要动态初始化锁

    vector<pthread_t> tids;            // 存储线程ID
    vector<threadData *> thread_datas; // 存储线程数据
    
    // 创建多个线程
    for (int i = 1; i <= NUM; i++)
    {
        pthread_t tid;
        threadData *td = new threadData(i /*, &lock*/);
        thread_datas.push_back(td);
        pthread_create(&tid, nullptr, getTicket, thread_datas[i - 1]);
        tids.push_back(tid);
    }

    // 等待所有线程结束
    for (auto thread : tids)
    {
        pthread_join(thread, nullptr);
    }

    // 清理线程数据
    for (auto td : thread_datas)
    {
        delete td;
    }

    // pthread_mutex_destroy(&lock);  // 如果使用动态初始化，这里需要销毁锁
    return 0;
}

// 下面注释的代码是一个线程本地存储(TLS)的示例
/*
#define NUM 3

// TLS变量声明
__thread unsigned int number = 0;
__thread int pid = 0;

struct threadData
{
    string threadname;
};

// 将pthread_t转换为十六进制字符串
string toHex(pthread_t tid)
{
    char buffer[128];
    snprintf(buffer, sizeof(buffer), "0x%x", tid);
    return buffer;
}

void InitThreadData(threadData *td, int number)
{
    td->threadname = "thread-" + to_string(number);
}

// 线程函数
void *threadRoutine(void *args)
{
    pthread_detach(pthread_self());  // 设置线程分离状态

    threadData *td = static_cast<threadData *>(args);
    string tid = toHex(pthread_self());
    int pid = getpid();

    int i = 0;
    while (i < 10)
    {
        cout << "tid: " << tid << ", pid: " << pid << endl;
        sleep(1);
        i++;
    }

    delete td;
    return nullptr;
}
*/